package com.icebergteam.warfacewidget.core.connection;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLDecoder;

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.json.JSONObject;

import com.icebergteam.warfacewidget.AppManager;
import com.icebergteam.warfacewidget.core.LogManager;
import com.icebergteam.warfacewidget.core.connection.services.Service;
import com.icebergteam.warfacewidget.core.utils.ViewUtils;

import android.content.Context;
import android.net.ConnectivityManager;
import android.os.StrictMode;

public class NetworkManager {
	public static final String className = NetworkManager.class.getCanonicalName();
	////////////////////////// Links
	// Masks
	private static final String regionMask		= "%region%";
	private static final String languageMask	= "%lang%";
	private static final String serviceMask		= "%service%"; 
	
	// URI template
	private static final String uriTemplateLink = "http://wf.mail" + regionMask + serviceMask + languageMask; 
	// Domain prefix
	private static final String domainPrefix = "http://wf.mail";
	
	public static void setupPolicy(){
	    StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().permitAll().build());
	}
	
	public static  String getUri(Service service) throws Exception {
		return getUri(service, AppManager.getGeneralSettings().getServerRegion(), false);
	}
	
	public static  String getUri(Service service, String regionSuffix) throws Exception {
		return getUri(service, regionSuffix, false);
	}
	
	public static  String getUri(Service service, boolean languageDepended) throws Exception {
		return getUri(service, AppManager.getGeneralSettings().getServerRegion(), languageDepended);
	}
	
	public static String getUri(Service service, String regionSuffix, boolean languageDepended) throws Exception {
		if(!service.isValid())
			throw new Exception(LogManager.getExecuteMethodName() + " ERROR: Invalid service path");
			
		String uri			= uriTemplateLink;
		String region		= regionSuffix;
		String lang			= languageDepended ? AppManager.getGeneralSettings().getServerLang() + "/" : "";
		uri = uri.replaceAll(regionMask,	region);
		uri = uri.replaceAll(serviceMask,	service.getPath());
		uri = uri.replaceAll(languageMask,	lang);
		uri += (service.hasParameters() ? "?" + service.getParameters() : "");
	
		return uri;
	}
		
	public static String getDomainLink() throws Exception{
			return getDomainLink(AppManager.getGeneralSettings().getServerRegion());
	}
	
	public static String getDomainLink(String regionSuffix) throws Exception{
		return domainPrefix + regionSuffix;
	}
	public static String getCustomDomainLink(String urlStr) throws Exception{
		URL url = new URL(URLDecoder.decode(urlStr));
		return String.format("%s://%s", url.getProtocol(), url.getHost());
	}
	////////////////////////// Get objects	
	final static int TIMEOUT_CONNECTION	= 30000;
	final static int TIMEOUT_SOCKET		= 50000;
	
	public static JSONObject getJSON(String uri) throws Exception, NetworkException {
		return getJSON(new HttpGet(uri));
	}
	
	public static JSONObject getJSON(HttpGet request) throws Exception, NetworkException {
		// Setup header parameters need to download JSON
		request.setHeader("Accept", "application/json, text/javascript, */*");
		request.setHeader("X-Requested-With", "XMLHttpRequest");
		
		return new JSONObject(getResponse(request));
	}
	
	public static String getHtml(String uri) throws Exception, NetworkException {
		
		return getHtml(new HttpGet(uri));
	}
	
	public static String getHtml(HttpGet request) throws Exception, NetworkException {
		return getResponse(request);
	}
	
	private static String getResponse(HttpGet request) throws Exception, NetworkException {

		NetworkManager.setupPolicy();
		// Check Internet connection
		HttpClient httpclient = null;
		try{
			if(!isNetworkConnectectionEnabled(AppManager.getContext()))
		
			throw new Exception(LogManager.getExecuteMethodName()+ " ERROR: Internet connection isn`t avaliable");
		
			HttpParams httpParameters = new BasicHttpParams();
			HttpConnectionParams.setConnectionTimeout(httpParameters, TIMEOUT_CONNECTION);
			HttpConnectionParams.setSoTimeout(httpParameters, TIMEOUT_SOCKET);
			// 
			httpclient = new DefaultHttpClient(httpParameters);
			HttpResponse response = httpclient.execute(request);
			
			StatusLine statusLine = response.getStatusLine();
		    if(statusLine.getStatusCode() == HttpStatus.SC_OK){
		        ByteArrayOutputStream out = new ByteArrayOutputStream();
		        response.getEntity().writeTo(out);
		        out.close();
		        String responseString = out.toString();
		        LogManager.LogV(className, LogManager.getExecuteMethodName(), "response status", "ok");
		       
		        return responseString;
		    } else{
		        //Closes the connection.
		    	httpclient.getConnectionManager().shutdown();
		    	LogManager.LogEA(className, statusLine.getStatusCode());
		    	throw new NetworkException( statusLine.getReasonPhrase(), statusLine.getStatusCode());
		    }
	   } finally{
		   if(httpclient != null){
			   httpclient.getConnectionManager().shutdown();
		   }
	   }
	}
	
	public static InputStream getResponseInputStream(String uri) throws IOException {
		return getResponseInputStream(new HttpGet(uri));
	}
	
	public static InputStream getResponseInputStream(HttpGet request) throws IOException {
		// Check Internet connection
		HttpClient httpclient = null;
		try{
			if(!isNetworkConnectectionEnabled(AppManager.getContext()))
		
			throw new IOException(LogManager.getExecuteMethodName()+ " ERROR: Internet connection isn`t avaliable");
		
			HttpParams httpParameters = new BasicHttpParams();
			HttpConnectionParams.setConnectionTimeout(httpParameters, TIMEOUT_CONNECTION);
			HttpConnectionParams.setSoTimeout(httpParameters, TIMEOUT_SOCKET);
			// 
			httpclient = new DefaultHttpClient(httpParameters);
			HttpResponse response = httpclient.execute(request);
			
			StatusLine statusLine = response.getStatusLine();
		    if(statusLine.getStatusCode() == HttpStatus.SC_OK){
		       InputStream responseInputStream = response.getEntity().getContent();
		        LogManager.LogVA(className, "response status", "ok", responseInputStream);
		       
		        return responseInputStream;
		    } else{
		        //Closes the connection.
		    	httpclient.getConnectionManager().shutdown();
		        throw new NetworkException( statusLine.getReasonPhrase(), statusLine.getStatusCode());
		    }
	   } 
		catch(Exception e){
			if(httpclient!= null){
				httpclient.getConnectionManager().shutdown();
			}
			LogManager.LogEA(className, ViewUtils.getErrorMessage(e));
			throw new IOException(ViewUtils.getErrorMessage(e));
		}
	}
	
	public static boolean isNetworkConnectectionEnabled(Context context) {
		final android.net.NetworkInfo network = getNetworkInfo(context); 
		return (network != null);
	}

	public static android.net.NetworkInfo getNetworkInfo(Context context) {
		final ConnectivityManager connMgr = (ConnectivityManager) context
				.getSystemService(Context.CONNECTIVITY_SERVICE);
		return connMgr.getActiveNetworkInfo();
	}
	
	public static boolean isWifiActiveNetwork(Context context){
		return true;
		//final android.net.NetworkInfo network = getNetworkInfo(context); 
		//return network.isAvailable() && network.getType() == ConnectivityManager.TYPE_WIFI;
	}
}
